"use client"; import { useEffect, useRef, useState } from "react"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { Notice } from "@/components/ui"; type T = { inquiry: { id: string; status: string; category: string; recipientUserId: string }; listing: { slug: string; title: string | null; status: string } | null; other: { id: string; name: string }; me: string; messages: { id: string; senderId: string; body: string; createdAt: string; readAt: string | null }[] }; export function ThreadView({ t }: { t: T }) { const [msgs, setMsgs] = useState(t.messages); const [body, setBody] = useState(""); const [busy, setBusy] = useState(false); const [err, setErr] = useState(null); const end = useRef(null); const router = useRouter(); useEffect(() => { end.current?.scrollIntoView({ block: "end" }); }, [msgs.length]); useEffect(() => { const i = setInterval(async () => { const r = await fetch(`/api/inquiries/${t.inquiry.id}/messages`); if (r.ok) { const j = await r.json(); setMsgs(j.messages.map((m: { id: string; senderId: string; body: string; createdAt: string; readAt: string | null }) => ({ ...m }))); } }, 15000); return () => clearInterval(i); }, [t.inquiry.id]); const send = async () => { if (!body.trim()) return; setBusy(true); setErr(null); const key = `${Date.now()}-${Math.random().toString(36).slice(2)}`; const r = await fetch(`/api/inquiries/${t.inquiry.id}/messages`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ body, idempotencyKey: key }) }); const j = await r.json(); setBusy(false); if (!r.ok) { setErr(j.error?.message ?? "Erreur"); return; } if (j.message) setMsgs((m) => [...m, { ...j.message }]); setBody(""); }; const setStatus = async (status: string) => { await fetch(`/api/inquiries/${t.inquiry.id}/messages`, { method: "PATCH", headers: { "content-type": "application/json" }, body: JSON.stringify({ status }) }); router.refresh(); }; const report = async () => { const details = prompt("Décrivez le problème (arnaque, harcèlement, contenu inapproprié…)"); if (details == null) return; await fetch("/api/reports", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ targetType: "USER", targetId: t.other.id, reason: "autre", details }) }); alert("Signalement transmis. Merci."); }; const iAmOwner = t.inquiry.recipientUserId === t.me; return (
← Messages

{t.other.name}

{t.listing &&

Au sujet de {t.listing.title ?? "l'annonce"}{t.listing.status !== "PUBLISHED" ? " (plus en ligne)" : ""}

}
{t.inquiry.status === "OPEN" ? : }{iAmOwner && t.inquiry.status !== "BLOCKED" && }
{msgs.map((m) =>
{m.body}{new Date(m.createdAt).toLocaleString("fr-CA", { timeZone: "America/Toronto", dateStyle: "short", timeStyle: "short" })}{m.senderId === t.me && m.readAt ? " · lu" : ""}
)}
{t.inquiry.status === "BLOCKED" ? Conversation bloquée. : (
{ e.preventDefault(); send(); }} className="mt-2 flex gap-2">